use crate::errors::call_frame::CallFrame;
use crate::errors::errorkind::ErrorKind;
use std::fmt;

/// 运行时错误结构（用于 Interpreter）
/// 与 CompilerError 类似，但用于运行时阶段
#[derive(Debug, Clone)]
pub struct RuntimeError {
    pub kind: ErrorKind,
    pub message: String,
    pub description: Option<String>, // 错误详细描述
    pub file_path: Option<String>,
    pub line: Option<usize>,
    pub column: Option<usize>,
    pub call_stack: Vec<CallFrame>,
    pub environment: Option<String>,
    pub suggestion: Option<String>,
    pub note: Option<String>,
}

impl RuntimeError {
    pub fn new(kind: ErrorKind, message: String) -> Self {
        RuntimeError {
            kind,
            message,
            description: None,
            file_path: None,
            line: None,
            column: None,
            call_stack: Vec::new(),
            environment: None,
            suggestion: None,
            note: None,
        }
    }

    /// 添加详细描述
    pub fn with_description(mut self, description: String) -> Self {
        self.description = Some(description);
        self
    }

    pub fn with_suggestion(mut self, suggestion: String) -> Self {
        self.suggestion = Some(suggestion);
        self
    }

    pub fn with_note(mut self, note: String) -> Self {
        self.note = Some(note);
        self
    }

    /// 设置错误位置信息
    pub fn with_location(mut self, file_path: String, line: usize, column: usize) -> Self {
        self.file_path = Some(file_path);
        self.line = Some(line);
        self.column = Some(column);
        self
    }

    /// 设置完整的调用栈
    pub fn with_call_stack(mut self, call_stack: Vec<CallFrame>) -> Self {
        self.call_stack = call_stack;
        self
    }

    /// 添加单个调用栈帧
    pub fn with_call_frame(mut self, frame: CallFrame) -> Self {
        self.call_stack.push(frame);
        self
    }

    /// 设置环境状态信息
    pub fn with_environment(mut self, environment: String) -> Self {
        self.environment = Some(environment);
        self
    }
}

impl fmt::Display for RuntimeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 运行时错误格式
        writeln!(
            f,
            "运行时错误[{}]: {}",
            self.kind.code(),
            self.message
        )?;

        // 如果有详细描述，显示描述
        if let Some(ref description) = self.description {
            writeln!(f, "   |")?;
            writeln!(f, "   = 描述: {}", description)?;
        }

        // 显示错误位置
        if let (Some(file_path), Some(line), Some(column)) = 
            (&self.file_path, &self.line, &self.column)
        {
            writeln!(f, "  --> {}:{}:{}", file_path, line, column)?;
        }

        // 显示调用栈
        if !self.call_stack.is_empty() {
            writeln!(f, "   |")?;
            writeln!(f, "   = 调用栈:")?;

            for (i, frame) in self.call_stack.iter().enumerate() {
                let frame_info = if let (Some(file), Some(line), Some(col)) =
                    (&frame.file_path, &frame.line, &frame.column)
                {
                    format!("{} at {}:{}:{}", frame.function_name, file, line, col)
                } else {
                    frame.function_name.clone()
                };
                writeln!(f, "     {}. {}", i + 1, frame_info)?;
            }
        }

        // 显示环境状态
        if let Some(ref env) = self.environment {
            writeln!(f, "   |")?;
            writeln!(f, "   = 环境状态: {}", env)?;
        }

        // 显示建议
        if let Some(ref suggestion) = self.suggestion {
            writeln!(f, "   |")?;
            writeln!(f, "   = 帮助: {}", suggestion)?;
        }

        // 显示说明
        if let Some(ref note) = self.note {
            writeln!(f, "   |")?;
            writeln!(f, "   = 说明: {}", note)?;
        }

        Ok(())
    }
}

impl std::error::Error for RuntimeError {
    // 这个trait的方法已经有默认实现，我们可以不提供额外的实现
}

impl From<RuntimeError> for String {
    fn from(error: RuntimeError) -> String {
        format!("{}", error)
    }
}

/// 辅助函数：创建未定义标识符错误
pub fn undefined_identifier_error(name: &str) -> RuntimeError {
    RuntimeError::new(
        ErrorKind::UndefinedIdentifier,
        format!("未定义的标识符: {}", name),
    )
    .with_suggestion(format!("请检查 '{}' 的拼写，或确保它已被定义", name))
}

/// 辅助函数：创建类型不匹配错误
pub fn type_mismatch_error(expected: &str, found: &str) -> RuntimeError {
    RuntimeError::new(
        ErrorKind::TypeMismatch,
        format!("类型不匹配: 期望 {}, 但得到 {}", expected, found),
    )
}

/// 辅助函数：创建参数数量不匹配错误
pub fn argument_mismatch_error(expected: usize, found: usize) -> RuntimeError {
    RuntimeError::new(
        ErrorKind::ArgumentMismatch,
        format!(
            "参数数量不匹配: 期望 {} 个参数, 但得到 {} 个",
            expected, found
        ),
    )
}

/// 辅助函数：创建数组越界错误
pub fn index_out_of_bounds_error(index: usize, length: usize) -> RuntimeError {
    RuntimeError::new(
        ErrorKind::IndexOutOfBounds,
        format!(
            "数组索引越界: 索引 {} 超出范围（数组长度 {}）",
            index, length
        ),
    )
    .with_suggestion(format!(
        "有效的索引范围是 0 到 {}",
        length.saturating_sub(1)
    ))
}

/// 辅助函数：创建除以零错误
pub fn division_by_zero_error() -> RuntimeError {
    RuntimeError::new(ErrorKind::DivisionByZero, "不能除以零".to_string())
        .with_suggestion("请检查除数是否为零，或添加条件判断".to_string())
}

/// 辅助函数：创建无效操作错误
pub fn invalid_operation_error(operation: &str, types: &str) -> RuntimeError {
    RuntimeError::new(
        ErrorKind::InvalidOperation,
        format!("无效操作: {} 不支持 {}", types, operation),
    )
    .with_suggestion(format!(
        "请检查操作数的类型，确保它们支持 '{}' 操作",
        operation
    ))
}

/// 辅助函数：创建常量重新赋值错误
pub fn constant_reassignment_error(name: &str) -> RuntimeError {
    RuntimeError::new(
        ErrorKind::ConstantReassignment,
        format!("常量重新赋值: {}", name),
    )
    .with_suggestion(format!("{} 是常量，不能重新赋值", name))
}

/// 辅助函数：创建无效函数调用错误
pub fn invalid_function_call_error(func_name: &str) -> RuntimeError {
    RuntimeError::new(
        ErrorKind::InvalidFunctionCall,
        format!("无效的函数调用: {}", func_name),
    )
    .with_suggestion(format!(
        "请检查 '{}' 函数的参数类型和数量是否正确",
        func_name
    ))
}

/// 辅助函数：创建未定义函数错误
pub fn undefined_function_error(func_name: &str) -> RuntimeError {
    RuntimeError::new(
        ErrorKind::UndefinedFunction,
        format!("未定义的函数: {}", func_name),
    )
    .with_suggestion(format!("请检查 '{}' 的拼写，或确保它已被定义", func_name))
}

/// 辅助函数：创建超出作用域错误
pub fn out_of_scope_error(name: &str) -> RuntimeError {
    RuntimeError::new(ErrorKind::OutOfScope, format!("超出作用域: {}", name))
        .with_suggestion(format!("请确保 '{}' 在当前作用域内已定义", name))
}
